home *** CD-ROM | disk | FTP | other *** search
- //--------------------------------------------------------------------------
- //
- // Copyright (c) 2002, Colin Granville
- //
- // All rights reserved.
- //
- // Redistribution and use in source and binary forms, with or
- // without modification, are permitted provided that the following
- // conditions are met:
- //
- // * Redistributions of source code must retain the above copyright
- // notice, this list of conditions and the following disclaimer.
- //
- // * Redistributions in binary form must reproduce the above
- // copyright notice, this list of conditions and the following
- // disclaimer in the documentation and/or other materials
- // provided with the distribution.
- //
- // * The name Colin Granville may not be used to endorse or promote
- // products derived from this software without specific prior
- // written permission.
- //
- // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- // COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- // OF THE POSSIBILITY OF SUCH DAMAGE.
- //
- //--------------------------------------------------------------------------
-
- #include "GuiTargets.h"
- #include "GuiTask.h"
- #include "GuiToolbox.h"
- #include "GuiWindow.h"
- #include "ERROR.h"
- #include <stdlib.h>
-
- GuiEventTarget::~GuiEventTarget() {}
-
- inline unsigned int monotonic_time() {return _swi(OS_ReadMonotonicTime,_RETURN(0));}
-
- class Initialise
- {
- public:
- Initialise();
-
- private:
- GUI_DECLARE_EVENT_TARGETS(Initialise);
-
- Claim toolbox_error(GuiToolboxEvent &event,const GuiIdBlock&);
- Claim quit_quit(GuiToolboxEvent &event,const GuiIdBlock&);
- Claim default_redraw(GuiWimpPollBlock& blk,const GuiIdBlock&);
- Claim default_key_press(GuiWimpPollBlock& blk,const GuiIdBlock&);
- Claim quit_message(GuiWimpMessage&);
- };
-
- Initialise::Initialise()
- {
- new GuiToolboxTarget(0,GuiToolbox::Error::Event,this,Initialise::toolbox_error);
- new GuiToolboxTarget(0,0x82a90+1,this,Initialise::quit_quit);
- new GuiWimpTarget(0,GuiWimp_ERedrawWindow,this,Initialise::default_redraw);
- new GuiWimpTarget(0,GuiWimp_EKeyPressed,this,Initialise::default_key_press);
- new GuiMessageTarget(GuiWimp_MQuit,this,Initialise::quit_message);
- }
- //*********************************************************************
-
- Claim Initialise::toolbox_error(GuiToolboxEvent &event,const GuiIdBlock&)
- {
- GuiToolbox::Error* err=(GuiToolbox::Error*)&event;
- WARN((_kernel_oserror*)&err->errnum);
- return CLAIM;
- }
-
- //*********************************************************************
-
- Claim Initialise::quit_quit(GuiToolboxEvent&,const GuiIdBlock&)
- {
- exit(0);
- return CLAIM;
- }
-
- //*********************************************************************
-
- Claim Initialise::default_redraw(GuiWimpPollBlock& blk,const GuiIdBlock&)
- {
- GuiRedrawWindowBlock& rb = (GuiRedrawWindowBlock&)blk;
- int more=0;
- GuiWindow::redraw(rb,more);
- while (more) GuiWindow::getRectangle(rb,more);
- return CLAIM;
- }
-
- //*********************************************************************
-
- Claim Initialise::default_key_press(GuiWimpPollBlock& blk,const GuiIdBlock&)
- {
- _swi(Wimp_ProcessKey,_IN(0),blk.keyPressed.keyCode);
- return CLAIM;
- }
-
- //*********************************************************************
-
- Claim Initialise::quit_message(GuiWimpMessage&)
- {
- exit(0);
- return CLAIM;
- }
- //********************************************************************************
-
- GuiIdBlock* id_block;
-
- void GuiRegister::initialise(GuiIdBlock& id_blk)
- {
- if (id_block!=0) return;
- id_block=&id_blk;
- new Initialise;
- }
-
- //********************************************************************************
- //********************************************************************************
-
- class GuiNullEventRegisterItem
- {
- public:
- GuiNullEventRegisterItem* next;
- GuiNullEventRegisterItem* previous;
- unsigned int interval;
- unsigned int call_time;
- GuiNullEventTarget* command;
- int thread_count;
-
- bool is_deleted() {return command==0;}
-
- bool match(unsigned int null_time) {return !is_deleted() && call_time<=null_time;}
- GuiNullEventRegisterItem* dispatch(GuiNullEventRegisterItem** first);
- void remove(GuiNullEventRegisterItem** first)
- {
- if (thread_count)
- {
- if (command) {command->item=0;command=0;}
- }
- else
- {
- if (command) command->item=0;
- if (next) next->previous=previous;
- if (previous)
- previous->next=next;
- else
- *first=next;
- if (command) {command->item=0;command=0;}
- delete this;
- }
- }
- };
-
- //********************************************************************************
-
- GuiNullEventRegisterItem* GuiNullEventRegisterItem::dispatch(GuiNullEventRegisterItem** first)
- {
- thread_count++;
- if (command) command->execute();
- thread_count--;
- GuiNullEventRegisterItem* next_item=next;
- if (is_deleted() && thread_count==0) remove(first);
- return next_item;
- }
-
- //********************************************************************************
-
- class GuiNullEventRegister
- {
- public:
- GuiNullEventRegister();
- GuiNullEventRegisterItem* add(unsigned int interval,GuiNullEventTarget* command);
- void remove(GuiNullEventRegisterItem*);
- void dispatch();
- unsigned int get_null_event_time() const {return null_event_time;}
- unsigned int get_minimum_return_time() const {return minimum_return_time;}
- void set_interval(GuiNullEventRegisterItem*,unsigned int interval);
-
- operator const void*() const {return first;}
- operator void*() {return first;}
- bool operator!() const {return first==0;}
- private:
- GuiNullEventRegisterItem* first;
- unsigned int null_event_time;
- unsigned int minimum_return_time;
- } null_event_register;
-
- //********************************************************************************
-
- GuiNullEventRegister::GuiNullEventRegister()
- : first(0),
- null_event_time(monotonic_time()),
- minimum_return_time(null_event_time)
- {
- }
- //********************************************************************************
- void GuiNullEventRegister::dispatch()
- {
- null_event_time=monotonic_time();
- GuiNullEventRegisterItem* p=first;
- GuiNullEventRegisterItem* next;
- unsigned int min_time=0xffffffff;
- minimum_return_time=min_time;
- while (p)
- {
- if (!p->is_deleted())
- {
- if (p->call_time<=null_event_time)
- {
- next = p->dispatch(&first);
- p->call_time=null_event_time+p->interval;
- if (p->call_time<min_time) min_time=p->call_time;
- p=next;
- }
- else
- {
- if (p->call_time<min_time) min_time=p->call_time;
- p=p->next;
- }
- }
- else p=p->next;
- }
- if (min_time<minimum_return_time) minimum_return_time=min_time;
- }
-
-
- //********************************************************************************
-
- GuiNullEventRegisterItem* GuiNullEventRegister::add(unsigned int interval,GuiNullEventTarget* command)
- {
- GuiNullEventRegisterItem* p=new GuiNullEventRegisterItem;
- if (p)
- {
- p->interval=interval;
- p->call_time=interval+null_event_time;
- p->command=command;
- p->thread_count=0;
- if (p->call_time<minimum_return_time) minimum_return_time=p->call_time;
- p->next=first;
- p->previous=0;
- if (p->next) p->next->previous=p;
- first=p;
- }
- return p;
- }
-
- //********************************************************************************
-
- void GuiNullEventRegister::remove(GuiNullEventRegisterItem* item)
- {
- if (item) item->remove(&first);
- }
-
- //********************************************************************************
-
- void GuiNullEventRegister::set_interval(GuiNullEventRegisterItem* item,unsigned int interval)
- {
- if (item)
- {
- item->interval=interval;
- unsigned int call_time=null_event_time+interval;
- if (call_time<minimum_return_time) minimum_return_time=call_time;
- }
- }
- //********************************************************************************
- //********************************************************************************
-
- GuiNullEventTarget::GuiNullEventTarget()
- : item(0) {}
-
- //********************************************************************************
-
- GuiNullEventTarget::GuiNullEventTarget(unsigned int interval)
- : item(0)
- {
- setInterval(interval);
- }
- //********************************************************************************
-
- GuiNullEventTarget::~GuiNullEventTarget() {destroy();}
-
- //********************************************************************************
-
- void GuiNullEventTarget::setInterval(unsigned int interval)
- {
- if (item)
- null_event_register.set_interval(item,interval);
- else
- item=null_event_register.add(interval,this);
- }
-
- //********************************************************************************
-
- void GuiNullEventTarget::destroy()
- {
- if (item) null_event_register.remove(item);
- }
- //********************************************************************************
- //********************************************************************************
- //********************************************************************************
-
- class GuiWimpRegisterItem
- {
- public:
- GuiWimpRegisterItem* next;
- GuiWimpRegisterItem* previous;
- GuiObjectId id;
- int event_code;
- GuiWimpEventTarget* command;
- int thread_count;
-
- bool is_deleted() {return command==0;}
- bool match(const GuiIdBlock& id_block) {return !is_deleted() &&
- (id_block.self.id==id || id==NULL_GuiObjectId);}
- GuiWimpRegisterItem* dispatch(GuiWimpPollBlock& wpb,const GuiIdBlock& id_block,GuiWimpRegisterItem** first);
- void remove(GuiWimpRegisterItem** first)
- {
- if (thread_count)
- {
- if (command) {command->item=0;command=0;}
- }
- else
- {
- if (next) next->previous=previous;
- if (previous)
- previous->next=next;
- else
- *first=next;
- delete this;
- if (command) {command->item=0;command=0;}
- }
- }
- };
-
- //********************************************************************************
-
- GuiWimpRegisterItem* GuiWimpRegisterItem::dispatch(GuiWimpPollBlock& wpb,const GuiIdBlock& id_block,
- GuiWimpRegisterItem** first)
- {
- thread_count++;
- Claim claim=(is_deleted())?DONT_CLAIM:command->execute(wpb,id_block);
- thread_count--;
- GuiWimpRegisterItem* next_item=next;
- if (is_deleted() && thread_count==0) remove(first);
- return (claim==DONT_CLAIM)?next_item:0;
- }
-
- //********************************************************************************
-
- class GuiWimpRegister
- {
- public:
- GuiWimpRegisterItem* add(int event_code,GuiObjectId,GuiWimpEventTarget*);
- void remove(GuiWimpRegisterItem*);
- void dispatch(int event_code,GuiWimpPollBlock& wpb,const GuiIdBlock& id_block);
-
- private:
- GuiWimpRegisterItem* event_list[32];
- }wimp_register;
-
- //********************************************************************************
- void GuiWimpRegister::dispatch(int event_code,GuiWimpPollBlock& wpb,const GuiIdBlock& id_block)
- {
- if (event_code>=32) return;
- GuiWimpRegisterItem** first=&event_list[event_code];
- GuiWimpRegisterItem* p=*first;
- while (p)
- {
- if (p->match(id_block))
- p = p->dispatch(wpb,id_block,first);
- else p=p->next;
- }
- }
-
-
- //********************************************************************************
-
- GuiWimpRegisterItem* GuiWimpRegister::add(int event_code,GuiObjectId id,GuiWimpEventTarget* command)
- {
- if (event_code>=32) return 0;
- GuiWimpRegisterItem* p=new GuiWimpRegisterItem;
- if (p)
- {
- p->id=id;
- p->event_code=event_code;
- p->command=command;
- p->thread_count=0;
-
- p->next=event_list[event_code];;
- p->previous=0;
- if (p->next) p->next->previous=p;
- event_list[event_code]=p;
- }
- return p;
- }
-
- //********************************************************************************
-
- void GuiWimpRegister::remove(GuiWimpRegisterItem* item)
- {
- if (item) item->remove(&event_list[item->event_code]);
- }
-
- //********************************************************************************
- //********************************************************************************
-
- GuiWimpEventTarget::GuiWimpEventTarget() : item(0) {}
-
- GuiWimpEventTarget::GuiWimpEventTarget(const GuiObject* obj, int event_code)
- : item(0)
- {
- setListener(obj,event_code);
- }
- //********************************************************************************
-
- GuiWimpEventTarget::~GuiWimpEventTarget() {destroy();}
-
- //********************************************************************************
-
- void GuiWimpEventTarget::setListener(const GuiObject* object, int event_code)
- {
- if (item) destroy();
- GuiObjectId object_id =(object)?object->id():NULL_GuiObjectId;
- item=wimp_register.add(event_code,object_id,this);
- }
- //********************************************************************************
-
- void GuiWimpEventTarget::destroy()
- {
- if (item) wimp_register.remove(item);
- }
- //********************************************************************************
- //********************************************************************************
-
- class GuiToolboxRegisterItem
- {
- public:
- GuiToolboxRegisterItem* next;
- GuiToolboxRegisterItem* previous;
- int event_code;
- GuiObjectId id;
- GuiToolboxEventTarget* command;
- int thread_count;
-
- bool is_deleted() {return command==0;}
- bool match(int event_code,const GuiIdBlock& id_block)
- {return !is_deleted() &&
- event_code==GuiToolboxRegisterItem::event_code &&
- (id_block.self.id==id || id_block.ancestor.id==id || id==NULL_GuiObjectId);}
-
- GuiToolboxRegisterItem* dispatch(GuiToolboxEvent& tbe,const GuiIdBlock& id_block,
- GuiToolboxRegisterItem** first);
- void remove(GuiToolboxRegisterItem** first)
- {
- if (thread_count)
- {
- if (command) {command->item=0;command=0;}
- }
- else
- {
- if (next) next->previous=previous;
- if (previous)
- previous->next=next;
- else
- *first=next;
- if (command) {command->item=0;command=0;}
- delete this;
- }
- }
- };
-
- //********************************************************************************
-
- GuiToolboxRegisterItem* GuiToolboxRegisterItem::dispatch(GuiToolboxEvent& tbe,
- const GuiIdBlock& id_block,GuiToolboxRegisterItem** first)
- {
- thread_count++;
- Claim claim=(is_deleted())?DONT_CLAIM:command->execute(tbe,id_block);
- thread_count--;
- GuiToolboxRegisterItem* next_item=next;
- if (is_deleted() && thread_count==0) remove(first);
- return (claim==DONT_CLAIM)?next_item:0;
- }
-
- //********************************************************************************
-
- class GuiToolboxRegister
- {
- public:
- GuiToolboxRegisterItem* add(int event_code,GuiObjectId,GuiToolboxEventTarget*);
- void remove(GuiToolboxRegisterItem*);
- void dispatch(GuiToolboxEvent& tbe, const GuiIdBlock& id_block);
-
- private:
- unsigned int hash(unsigned int event) {return (event & 0xf) | ((event & 0xf00)>>4);}
- GuiToolboxRegisterItem* event_list[256];
- }toolbox_register;
-
- //********************************************************************************
-
-
- void GuiToolboxRegister::dispatch(GuiToolboxEvent& tbe, const GuiIdBlock& id_block)
- {
- GuiToolboxRegisterItem** first=&event_list[hash(tbe.eventCode)];
- GuiToolboxRegisterItem* p=*first;
- while (p)
- {
- if (p->match(tbe.eventCode,id_block))
- p = p->dispatch(tbe,id_block,first);
- else
- p=p->next;
- }
- }
-
- //********************************************************************************
-
- GuiToolboxRegisterItem* GuiToolboxRegister::add(int event_code,GuiObjectId id,
- GuiToolboxEventTarget* command)
- {
- GuiToolboxRegisterItem* p=new GuiToolboxRegisterItem;
- if (p)
- {
- p->event_code=event_code;
- p->id=id;
- p->command=command;
- p->thread_count=0;
- unsigned int i=hash(event_code);
- p->next=event_list[i];
- p->previous=0;
- if (p->next) p->next->previous=p;
- event_list[i]=p;
- }
- return p;
- }
-
- //********************************************************************************
-
- void GuiToolboxRegister::remove(GuiToolboxRegisterItem* item)
- {
- if (item) item->remove(&event_list[hash(item->event_code)]);
- }
-
- //********************************************************************************
- //********************************************************************************
-
- GuiToolboxEventTarget::GuiToolboxEventTarget() : item(0) {}
-
- GuiToolboxEventTarget::GuiToolboxEventTarget(const GuiObject* obj, int event_code)
- : item(0)
- {
- setListener(obj,event_code);
- }
- //********************************************************************************
-
- GuiToolboxEventTarget::~GuiToolboxEventTarget() {destroy();}
-
- //********************************************************************************
-
- void GuiToolboxEventTarget::setListener(const GuiObject* object, int event_code)
- {
- if (item) destroy();
- GuiObjectId object_id =(object)?object->id():NULL_GuiObjectId;
- item=toolbox_register.add(event_code,object_id,this);
- }
- //********************************************************************************
-
- void GuiToolboxEventTarget::destroy()
- {
- if (item) toolbox_register.remove(item);
- }
-
- //********************************************************************************
- //********************************************************************************
- //********************************************************************************
-
- class GuiMessageRegisterItem
- {
- public:
- GuiMessageRegisterItem* next;
- GuiMessageRegisterItem* previous;
- int message_code;
- GuiMessageEventTarget* command;
- int thread_count;
-
- bool is_deleted() {return command==0;}
-
- bool match(int message) {return !is_deleted() && message==message_code;}
- GuiMessageRegisterItem* dispatch(GuiWimpMessage& wm,GuiMessageRegisterItem** first);
- void remove(GuiMessageRegisterItem** first)
- {
- if (thread_count)
- {
- if (command) {command->item=0;command=0;}
- }
- else
- {
- if (next) next->previous=previous;
- if (previous)
- previous->next=next;
- else
- *first=next;
- if (command) {command->item=0;command=0;}
- delete this;
- }
- }
-
- };
-
- //********************************************************************************
-
- GuiMessageRegisterItem* GuiMessageRegisterItem::dispatch(GuiWimpMessage& wm,
- GuiMessageRegisterItem** first)
- {
- thread_count++;
- Claim claim=(is_deleted())?DONT_CLAIM:command->execute(wm);
- thread_count--;
- GuiMessageRegisterItem* next_item=next;
- if (is_deleted() && thread_count==0) remove(first);
- return (claim==DONT_CLAIM)?next_item:0;
- }
-
- //********************************************************************************
-
- class GuiMessageRegister
- {
- public:
- GuiMessageRegisterItem* add(int message_code,GuiMessageEventTarget*);
- void remove(GuiMessageRegisterItem*);
- void dispatch(GuiWimpMessage& wm);
-
- private:
- unsigned int hash(int message_code) {return (message_code & 7) | ((message_code & 0x7c0)>>3);}
- GuiMessageRegisterItem* event_list[256];
- }message_register;
-
- //********************************************************************************
-
- void GuiMessageRegister::dispatch(GuiWimpMessage& wm)
- {
- GuiMessageRegisterItem** first=&event_list[hash(wm.hdr.actionCode)];
- GuiMessageRegisterItem* p=*first;
- while (p)
- {
- if (p->match(wm.hdr.actionCode))
- p=p->dispatch(wm,first);
- else p=p->next;
- }
- }
-
- //********************************************************************************
-
- GuiMessageRegisterItem* GuiMessageRegister::add(int message_code,GuiMessageEventTarget* command)
- {
- GuiMessageRegisterItem* p=new GuiMessageRegisterItem;
- if (p)
- {
- p->message_code=message_code;
- p->command=command;
- p->thread_count=0;
- unsigned int i=hash(message_code);
- p->next=event_list[i];
- p->previous=0;
- if (p->next) p->next->previous=p;
- event_list[i]=p;
- }
- return p;
- }
-
- //********************************************************************************
-
- void GuiMessageRegister::remove(GuiMessageRegisterItem* item)
- {
- if (item) item->remove(&event_list[hash(item->message_code)]);
- }
-
- //********************************************************************************
- //********************************************************************************
-
- GuiMessageEventTarget::GuiMessageEventTarget() : item(0) {}
-
- GuiMessageEventTarget::GuiMessageEventTarget(int message_code)
- : item(0)
- {
- setListener(message_code);
- }
- //********************************************************************************
-
- GuiMessageEventTarget::~GuiMessageEventTarget() {destroy();}
-
- //********************************************************************************
-
- void GuiMessageEventTarget::setListener(int message_code)
- {
- if (item) destroy();
- item=message_register.add(message_code,this);
- }
- //********************************************************************************
-
- void GuiMessageEventTarget::destroy()
- {
- if (item) message_register.remove(item);
- }
-
- //********************************************************************************
- //********************************************************************************
- //********************************************************************************
-
- int mask;
-
- void GuiRegister::dispatch(int event_code,GuiWimpPollBlock& poll_block)
- {
- if (id_block==0) return;
- if (event_code<32)
- {
- switch (event_code)
- {
- case GuiWimp_ENull: null_event_register.dispatch();
- break;
- case 17:
- case 18: message_register.dispatch(*(GuiWimpMessage*)&poll_block);
- return;
- }
- wimp_register.dispatch(event_code,poll_block,*id_block);
- }
- else if (event_code==0x200)
- toolbox_register.dispatch(*(GuiToolboxEvent*)&poll_block,*id_block);
- }
-
-
- //********************************************************************************
-
- void GuiRegister::poll(int *ev_code, GuiWimpPollBlock* poll_blk, int* poll_w)
- {
- static GuiWimpPollBlock _poll_block;
- int _event_code;
-
- GuiWimpPollBlock* poll_block=(poll_blk)?poll_blk:&_poll_block;
- int* event_code=(ev_code)?ev_code:&_event_code;
-
- if (!null_event_register)
- {
- _swix(Wimp_Poll,_INR(0,1) | _IN(3) | _OUT(0),mask | 1,poll_block,poll_w,event_code);
- }
- else if (null_event_register.get_minimum_return_time()<=
- null_event_register.get_null_event_time())
- {
- _swix(Wimp_Poll,_INR(0,1) | _IN(3) | _OUT(0),mask &~ 1,poll_block,poll_w,event_code);
- }
- else _swix(Wimp_PollIdle,_INR(0,3) | _OUT(0), mask &~ 1,poll_block,
- null_event_register.get_minimum_return_time(),poll_w,event_code);
-
- dispatch(*event_code,*poll_block);
- }
-
- //********************************************************************************
-
- unsigned int GuiRegister::get_null_event_time()
- {
- return null_event_register.get_null_event_time();
- }
-